/**
 * 
 */
package cn.ad.server.web.servlet.v2.requesthandler;

import cn.ad.server.web.log.IAdEventLogger;
import cn.ad.server.web.log.entity.AdserverEventLog;
import cn.ad.server.web.servlet.IllegalRequestException;
import cn.ad.server.web.servlet.v2.parser.HttpServletParser;
import cn.ad.server.web.spring.model.AdRequest;
import cn.ad.server.web.spring.model.AdResponse;
import cn.ad.server.web.spring.model.IAdserverRequest;
import cn.ad.server.web.spring.model.IAdserverResponse;
import cn.ad.server.web.spring.service.actions.IAdRequestAction;
import cn.ad.server.web.spring.service.actions.RequestActionException;
import cn.ad.server.web.utils.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Adserver 广告请求处理Servlet
 * @author Wu Chengjun
 *
 */
public abstract class AdRequestHandler extends AbstractRequestHandler{
	
	private static Logger LOGGER = LoggerFactory.getLogger(AdRequestHandler.class);
	
	/**
	 * 渠道参数名称，用于在路径获取请求字符串标识渠道的参数名称
	 */
	private static final String CHANNEL_PARAM_NAME = "ch";
	
	private static final String AVID_PARAM_NAME = "avid";
	
	/**
	 * Adserver 日志记录实现接口
	 */
	private IAdEventLogger adEventLogger;

	/**
	 * RequestAction 接口
	 */
	private IAdRequestAction requestAction;
	
	/**
	 * 请求解析类
	 */
	private HttpServletParser parser;
	
	
	/**
	 * 构造函数
	 */
	public AdRequestHandler() {
		super();
	}
	
	/**
	 * 验证请求有效性
	 * @param request
	 * @throws IllegalRequestException 如果验证失败则抛出非法请求异常
	 */
	public void validRequest(IAdserverRequest request) throws RequestParamValidFailedException{
	}
	
	/**
	 * 出项异常处理响应方法
	 * @param e
	 * @param response
	 */
	public void handleExceptionResponse(Exception e, HttpServletResponse response){
		if(e instanceof IllegalRequestException){
			response.setStatus(404);
		}else{
			response.setStatus(500);
		}
	}
	
	/**
	 * 处理响应结果
	 * @param response
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	public void handleResponse(HttpServletResponse response, HttpServletParser selvetParser, IAdserverRequest adrequest, IAdserverResponse adresponse) throws Exception {
		selvetParser.writeResponse(adresponse, response);
	}
	
	/*
	 * (non-Javadoc)
	 * @see cn.ad.server.web.servlet.v2.AdserverGenericServlet#doService(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response) throws RequestHandleException{
			try{
				
				HttpServletParser servletParser = getParser();
				
				if(servletParser == null){
					throw new NullPointerException("servletParser is null.");
				}
				
				
				IAdserverRequest adReq = servletParser.parse(request);
				if(adReq == null){
					throw new NullPointerException("AdRequest is null.");
				}
				
				validRequest(adReq);
				
				if(adReq instanceof AdRequest){
					AdResponse adRes = handleAdRquest((AdRequest) adReq);
					if(adRes == null){
						throw new NullPointerException("AdResponse is null.");
					}
					handleResponse(response, servletParser, adReq, adRes);
				}
			}catch(Exception e){
				LOGGER.error("Threre a exception at request's handle,error:{}", e.getMessage(), e);
				handleExceptionResponse(e, response);
			}
	}
	
	private AdResponse handleAdRquest(AdRequest adRequest) throws RequestActionException {
		return getRequestAction().doRequest(adRequest);
	}
	
	
	/**
	 * 获取请求版本号
	 * @param request
	 * @return
	 */
	protected String getVersion(HttpServletRequest request){
		// TODO 需要后期实现
		return null;
	}
	
	/**
	 * 获取请求来源接入渠道平台
	 * @param request
	 * @return
	 */
	protected String getChannel(HttpServletRequest request){
		return getChannelFromUriPath(request);
	}
	
	/**
	 * 获取请求来源接入DSP广告主标识
	 * @param request
	 * @return
	 */
	protected String getAvid(HttpServletRequest request){
		return getAvidFromUriPath(request);
	}
	
	
	/**
	 * 从请求路径中获取渠道标识
	 * @param request
	 * @return
	 */
	private String getChannelFromUriPath(HttpServletRequest request){
		String ch = HttpUtils.getPathParam(request.getServletPath(), CHANNEL_PARAM_NAME);
		return ch;
	}
	
	/**
	 * 从请求路径中获取DSP广告主标识
	 * @param request
	 * @return
	 */
	private String getAvidFromUriPath(HttpServletRequest request){
		String avid = HttpUtils.getPathParam(request.getServletPath(), AVID_PARAM_NAME);
		return avid;
	}

	/**
	 * @return the adEventLogger
	 */
	public IAdEventLogger getAdEventLogger() {
		return adEventLogger;
	}

	/**
	 * @param adEventLogger the adEventLogger to set
	 */
	public void setAdEventLogger(IAdEventLogger adEventLogger) {
		this.adEventLogger = adEventLogger;
	}

	/**
	 * 记录广告事件日志
	 * @param eventlog
	 */
	protected void logAdserverEventLog(AdserverEventLog eventlog){
		adEventLogger.log(eventlog);
	}


	/**
	 * @return the parser
	 */
	public HttpServletParser getParser() {
		return parser;
	}


	/**
	 * @param parser the parser to set
	 */
	public void setParser(HttpServletParser parser) {
		this.parser = parser;
	}


	/**
	 * @return the requestAction
	 */
	public IAdRequestAction getRequestAction() {
		return requestAction;
	}


	/**
	 * @param requestAction the requestAction to set
	 */
	public void setRequestAction(IAdRequestAction requestAction) {
		this.requestAction = requestAction;
	}
}
